<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>

  <body>
    <canvas id="c" width="400" height="300"></canvas>

    <script id="vertex-shader" type="x-shader/x-vertex">
      attribute vec4 a_position;
      uniform vec2 u_resolution;

      void main() {
        // (a_position is canvasPx)
        vec2 radio_position = a_position.xy / u_resolution;

        vec2 position = (radio_position * 2.0) - 1.0;

        gl_Position = vec4(position.xy,0,1);
      }
    </script>

    <script id="fragment-shader" type="x-shader/x-fragment">
      precision mediump float;
      uniform vec4 u_color;

      void main(){
        gl_FragColor = u_color;
      }
    </script>

    <script>
      window.onload = function () {
        const gl = document.querySelector('#c').getContext('webgl')

        if (!gl) return

        const vertexSource = document.querySelector('#vertex-shader').text
        const fragmentSource = document.querySelector('#fragment-shader').text

        // create shader
        function createShader(gl, type, source) {
          const shader = gl.createShader(type)
          gl.shaderSource(shader, source)
          // compile
          gl.compileShader(shader)

          //
          if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
            console.log(
              'compile shader had error',
              gl.COMPILE_STATUS,
              gl.getShaderInfoLog(shader)
            )
            gl.deleteShader(shader)
            return null
          }

          return shader
        }
        const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexSource)
        const fragmentShader = createShader(
          gl,
          gl.FRAGMENT_SHADER,
          fragmentSource
        )

        console.log(vertexShader, fragmentShader)

        // create shader program
        function createShaderProgram(gl, vertexShader, fragmentShader) {
          const program = gl.createProgram()
          // attach
          gl.attachShader(program, vertexShader)
          gl.attachShader(program, fragmentShader)
          gl.linkProgram(program)

          if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
            console.log('link program had error', gl.getProgramInfoLog(program))
            return null
          }

          return program
        }
        const shaderProgram = createShaderProgram(
          gl,
          vertexShader,
          fragmentShader
        )

        // read buffer
        const positionBuffer = gl.createBuffer()
        gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer)

        // read location
        const positionAttributeLocation = gl.getAttribLocation(
          shaderProgram,
          'a_position'
        )
        const resolutionUniformLocation = gl.getUniformLocation(
          shaderProgram,
          'u_resolution'
        )
        const colorUniformLocation = gl.getUniformLocation(
          shaderProgram,
          'u_color'
        )

        // read view
        gl.viewport(0, 0, gl.canvas.width, gl.canvas.height)
        gl.clearColor(0, 0, 0, 0)
        gl.clear(gl.COLOR_BUFFER_BIT)

        // to run program
        gl.useProgram(shaderProgram)
        gl.uniform2f(
          resolutionUniformLocation,
          gl.canvas.width,
          gl.canvas.height
        )
        gl.enableVertexAttribArray(positionAttributeLocation)

        const size = 2
        const type = gl.FLOAT
        const normalize = false
        const stride = 0
        const offset = 0
        gl.vertexAttribPointer(
          positionAttributeLocation,
          size,
          type,
          normalize,
          stride,
          offset
        )

        for (let i = 0; i < 10; i++) {
          setRectangle(
            gl,
            randomInt(400),
            randomInt(300),
            randomInt(400),
            randomInt(300)
          )

          gl.uniform4f(
            colorUniformLocation,
            Math.random(),
            Math.random(),
            Math.random(),
            1
          )

          // draw
          const primitiveType = gl.TRIANGLES
          const drawOffset = 0
          const drawCount = 6
          gl.drawArrays(primitiveType, drawOffset, drawCount)
        }

        function setRectangle(gl, x, y, width, height) {
          var x1 = x
          var x2 = x + width
          var y1 = y
          var y2 = y + height
          gl.bufferData(
            gl.ARRAY_BUFFER,
            new Float32Array([x1, y1, x2, y1, x1, y2, x1, y2, x2, y1, x2, y2]),
            gl.STATIC_DRAW
          )
        }

        // Returns a random integer from 0 to range - 1.
        function randomInt(range) {
          return Math.floor(Math.random() * range)
        }
      }
    </script>
  </body>
</html>
